package com.dream.app.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.dream.app.cache.AppGroupCache;
import com.dream.app.cache.AppGroupResourceCache;
import com.dream.app.cache.AppImageCache;
import com.dream.app.cache.AppOrgCache;
import com.dream.app.cache.AppPositionCache;
import com.dream.app.cache.AppResourceCache;
import com.dream.app.cache.AppUserResourceCache;
import com.dream.app.service.OrgService;
import com.dream.app.service.UserService;
import com.dream.base.web.service.FileUploadService;
import com.dream.dao.base.AppImageDAO;
import com.dream.dao.base.AppUserDAO;
import com.dream.dao.base.AppUserGroupDAO;
import com.dream.dao.base.AppUserResourceDAO;
import com.dream.model.app.AppAbstractUser;
import com.dream.model.app.AppAbstractUser.UserStatus;
import com.dream.model.app.AppGroup;
import com.dream.model.app.AppImage;
import com.dream.model.app.AppImage.ImageStatus;
import com.dream.model.app.AppOrg;
import com.dream.model.app.AppPosition;
import com.dream.model.app.AppPosition.PositionType;
import com.dream.model.app.AppResource;
import com.dream.model.app.AppUser;
import com.dream.model.app.AppUserGroup;
import com.dream.model.app.AppUserResource;
import com.dream.model.app.AppUserResource.AppUserResourcePK;
import com.dream.utils.hibernate.PagingVO;
import com.dream.vo.app.GroupVO;
import com.dream.vo.app.UserVO;
import com.google.common.collect.Lists;
/**
 * @copyright evan
 * @author evan
 * @date 2013/8/29
 */
@Service("UserService")
public class UserServiceImpl implements UserService{
	
	@Autowired
	private AppUserDAO appUserDAO;
	
	@Autowired
	private AppUserGroupDAO appUserGroupDAO;
	
	@Autowired
	private AppOrgCache appOrgCache;
	
	@Autowired
	private AppPositionCache appPositionCache;
	
	@Autowired
	private AppImageCache appImageCache;
	
	@Autowired
	private AppGroupCache appGroupCache;
	
	@Autowired
	private AppImageDAO appImageDAO;
	
	@Autowired
	private AppUserResourceDAO appUserResourceDAO;
	
	@Autowired
	private AppUserResourceCache appUserResourceCache;
	
	@Autowired
	private AppResourceCache appResourceCache;
	
	@Autowired
	private FileUploadService fileUploadService;
	
	@Autowired
	private AppGroupResourceCache appGroupResourceCache;
	
	
	@Autowired
	private OrgService orgService;
	
	@Override
	@Transactional
	public boolean isExistedUser(final String userId) {
		
		return appUserDAO.isExist(userId);
	}

	@Override
	@Transactional
	public AppUser addNew(final UserVO vo,final AppAbstractUser user) {
		
		 AppUser appUser = new AppUser();
		 populateUser(appUser,vo,user);
		 appUser.setId(vo.getId());
		 appUserDAO.save(appUser);
		 updateUserGroup(appUser.getId(),vo.getGroups(),user);
		 return appUser;
	}
	
	
	@Transactional
	private void updateUserGroup(final String userId,final String[] group,final AppAbstractUser user){
		
		if(StringUtils.isNotBlank(userId) && ArrayUtils.isNotEmpty(group)){
			
			appUserGroupDAO.deleteByUser(userId);
			for(String g : group){
				
				AppUserGroup ug = new AppUserGroup();
				ug.setUserId(userId);
				ug.setGroupId(g);
				ug.setDeleted(false);
				ug.setCreateTime(new Date());
				ug.setCreateUser(user.getId());
				appUserGroupDAO.save(ug);
			}
		}
	}
	
	@Transactional
	private void populateUserSetting(final AppUser appUser,final UserVO vo){
		 // 登录者对自己账户修改
		 appUser.setUpdateTime(new Date());
		 appUser.setUpdateUser(vo.getId());
		 appUser.setPositionId(Long.parseLong(vo.getPosition()));
		 appUser.setDisplay(true);
		 appUser.setImageId(vo.getImageId());
		 appUser.setMobile(vo.getMobile());
		 appUser.setName(vo.getName());
		 appUser.setStatus(UserStatus.active);
	}
	
	@Transactional
	private void populateUser(final AppUser appUser,final UserVO vo,final AppAbstractUser user){
		
		 appUser.setCreateTime(new Date());
		 appUser.setCreateUser(user.getId());
		 
		 Long position = Long.parseLong(vo.getPosition());
		 
		 appUser.setPositionId(position);
		 appUser.setDisplay(true);
		 appUser.setImageId(vo.getImageId());
		 appUser.setMobile(vo.getMobile());
		 appUser.setName(vo.getName());
		 
		 appUser.setOrgId(getOrg(position,vo));
		 if(StringUtils.isNotBlank(vo.getPassword())){
			 appUser.setPassword(vo.getPassword());
		 }
		 appUser.setStatus(UserStatus.active);
	}
	
	private Long getOrg(Long position,final UserVO vo){
		
		AppPosition pos = appPositionCache.getById(position);
		Long org = null;
		if(pos != null){
			
			//staff 必须设置办事处
			if(PositionType.staff.equals(pos.getType())){
				if(StringUtils.isBlank(vo.getSecondOrg())){
					throw new RuntimeException("staff user need second org");
				}
				return Long.parseLong(vo.getSecondOrg());
			}
			
			if(PositionType.manager.equals(pos.getType())){
				//manager 老板
				if(StringUtils.isBlank(vo.getFirstOrg())){
					return appOrgCache.getRoot().getId();
				}
				
				//manager 大区经理
				if(StringUtils.isNotBlank(vo.getFirstOrg()) && StringUtils.isBlank(vo.getSecondOrg())){
					return Long.parseLong(vo.getFirstOrg());
				}
				
				//manager 办事处经理
				if(StringUtils.isNotBlank(vo.getFirstOrg()) && StringUtils.isNotBlank(vo.getSecondOrg())){
					return Long.parseLong(vo.getSecondOrg());
				}
			}
			
		}
		
		return org;
	}
	
	@Override
	@Transactional
	public AppUser login(final UserVO vo) {
		
		AppUser user = appUserDAO.login(vo.getId(), vo.getPassword());
		setExtUserInfo(user);
		return user;
	}
	
	private void setExtUserInfo(final AppUser user){
		
		if(user != null){
			List<AppUserGroup> ugs = appUserGroupDAO.getByUser(user.getId());
			if(CollectionUtils.isNotEmpty(ugs)){
				List<AppGroup> li = Lists.newArrayList();
				for(AppUserGroup aug : ugs){
					li.add(appGroupCache.getById(aug.getGroupId()));
				}
				user.setGroups(li);
			}
			user.setImage(appImageCache.getById(user.getImageId()));
			user.setAppOrg(appOrgCache.getOrg(user.getOrgId()));
			user.setPosition(appPositionCache.getById(user.getPositionId()));
		}
		
	}
	@Override
	@Transactional
	public AppUser getDetail(final String userId) {
		
		AppUser user = appUserDAO.selectById(userId);
		setExtUserInfo(user);
		setOrg(user);
		return user;
	}

	@Override
	@Transactional
	public boolean findPwd(final UserVO vo) {
		AppUser user = appUserDAO.login(vo.getId(), vo.getPassword());
		return user != null? true:false ;
	}

	@Override
	@Transactional
	public void changePwd(final UserVO vo) {
		 AppUser appUser = appUserDAO.selectById(vo.getId());
		 // 密码修改
		 appUser.setPassword(vo.getNewPassword());
		 appUser.setUpdateTime(new Date());
		 appUser.setUpdateUser(vo.getId());
		 appUserDAO.saveOrUpdate(appUser);
	}

	@Override
	@Transactional
	public void modifyUser(final UserVO vo,final AppAbstractUser user) {
		
		 AppUser appUser = appUserDAO.selectById(vo.getId());
		 populateUser(appUser,vo,user);
		 appUserDAO.saveOrUpdate(appUser);
		 updateUserGroup(appUser.getId(),vo.getGroups(),user);
		
	}
	
	@Override
	@Transactional
	public void modifyUserSetting(final UserVO vo) {
		
		 AppUser appUser = appUserDAO.selectById(vo.getId());
		 // 修改账户信息
		 populateUserSetting(appUser,vo);
		 appUserDAO.saveOrUpdate(appUser);
		
	}

	@Override
	@Transactional
	public Boolean isLockedUser(final UserVO userVO,final int lockCount, final int unlockHours) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	@Transactional
	public AppImage uploadUserIamge(final AppAbstractUser user, final UserVO vo,final HttpServletRequest httpRequest) {
		
		AppImage img = null;
		MultipartFile file = fileUploadService.getUploadedFileInfo(httpRequest,vo.getImageFileId());
		if(file != null){
			
			
			if(vo.getImageId() != null){
				img = appImageCache.getById(vo.getImageId());
				img.setUpdateTime(new Date());
				img.setUpdateUser(user.getId());
			}else{
				img = new AppImage();
				img.setUri(UserVO.getUploadEntirePath(user));
				img.setThumbnailUri(UserVO.getUploadThumbPath(user));
				img.setCreateTime(new Date());
				img.setCreateUser(user.getId());
			}
			String[] imageInfo = file.getOriginalFilename().split("\\.");
			if(ArrayUtils.isNotEmpty(imageInfo) && imageInfo.length > 1){
				img.setName(imageInfo[0]);
				img.setImageType(imageInfo[1]);
				img.setStatus(ImageStatus.normal);
				appImageDAO.saveOrUpdate(img);
				fileUploadService.uploadFile(file,img.getThumbnailUri(), img.getThumbImgFullPath());
				appImageCache.reload();//reload from db
			}
		}
		return img;	
	}
	
	@Override
	@Transactional
	public PagingVO queryUser(final UserVO userVO,final PagingVO pageVO){
		
		List<Long> leafOrgs = orgService.getLeafOrgs(userVO.getFirstOrg(), userVO.getSecondOrg());
		userVO.setOrgs(leafOrgs);
		return appUserDAO.queryUser(userVO, pageVO);
	}

	@Override
	@Transactional
	public void delUser(final String userId, final AppAbstractUser admin) {
		
		AppUser user = appUserDAO.selectById(userId);
		if(user != null){
			user.setStatus(UserStatus.delete);
			user.setUpdateTime(new Date());
			user.setUpdateUser(admin.getId());
			appUserDAO.saveOrUpdate(user);
		}
	}

	@Override
	@Transactional
	public void modifyUserResource(final GroupVO vo,final  AppAbstractUser user) {
		
		final Long[] resources = vo.getResources();
		if(ArrayUtils.isNotEmpty(resources) && StringUtils.isNotBlank(vo.getUserId())){
			
			appUserResourceDAO.deleteByUser(vo.getUserId());
			for(Long id : resources){
				
				AppUserResource ar = new AppUserResource();
				AppUserResourcePK pk = new AppUserResourcePK();
				pk.setResourceId(id);
				pk.setUserId(vo.getUserId());
				ar.setId(pk);
				appUserResourceDAO.save(ar);
			}
			
			appUserResourceCache.reload(user);
		}
	}

	@Override
	@Transactional
	public List<AppResource> getMyResources(final  String  userId) {
		
		 List<AppResource> li = Lists.newArrayList();
		 
		 List<AppUserGroup> groups = appUserGroupDAO.getByUser(userId);
		 if(CollectionUtils.isNotEmpty(groups)){
			 for(AppUserGroup item : groups){
				 li.addAll(appGroupResourceCache.getMyResources(item.getGroupId()));
			 }
		 }
		 
		 List<AppUserResource> urList = appUserResourceDAO.getByUser(userId);
		
		 if(CollectionUtils.isNotEmpty(urList)){
			 for(AppUserResource ur : urList){
				 AppResource ar = appResourceCache.getById(Long.toString(ur.getId().getResourceId()));
				 if(!li.contains(ar)){
					 li.add(ar);
				 }
			 }
		 }
		
		 return li;
	}

	@Override
	@Transactional
	public List<AppUser> selectByStatus(UserStatus status) {
		return appUserDAO.getAllUserByStatus(status);
	}

	@Override
	@Transactional
	public List<Map<String, Object>> selectUser(String deptId,String positionType) {
		
		return appUserDAO.selectUser(deptId, positionType);
	}
	
	@Override
	@Transactional
	public List<Map<String, Object>> selectUser(String positionType) {
		
		return appUserDAO.selectUser(positionType);
	}
	
	private void setOrg(AppUser user){
		if(user != null){
			List<AppOrg> orgs = orgService.getParent(user.getOrgId());
			user.initOrgs(orgs);
		}
		
	}
	
}